package com.mini.spring.beanfactory;

import cn.hutool.core.bean.BeanUtil;
import com.mini.spring.BeanDefinition;
import com.mini.spring.BeanReference;
import com.mini.spring.Kv;
import com.mini.spring.beandefinitionregistry.BeanDefinitionRegistry;
import com.mini.spring.singleton.SingletonBeanRegistry;

import java.util.HashMap;
import java.util.Map;

public class DefaultBeanFactory extends SingletonBeanRegistry implements BeanFactory, BeanDefinitionRegistry {
    Map<String, BeanDefinition> definitionMap = new HashMap<>();

    @Override
    public void register(BeanDefinition beanDefinition) {
        definitionMap.put(beanDefinition.getName(), beanDefinition);
    }

    @Override
    public Object getBean(String beanName) {
        Object bean = getSingleton(beanName);
        if (bean != null) {
            return bean;
        }
        // 获取定义,生成bean
        BeanDefinition beanDefinition = getBeanDefinition(beanName);
        return doCreateBean(beanDefinition);
    }

    private Object doCreateBean(BeanDefinition beanDefinition) {
        try {
            Object bean = beanDefinition.getBeanClass().newInstance();
            // 填充属性
            for (Kv kv : beanDefinition.getValues()) {
                Object v = kv.getValue();
                if (v instanceof BeanReference) {
                    v = getBean(((BeanReference) v).getBeanName());
                }
                //通过反射设置属性
                BeanUtil.setFieldValue(bean, kv.getName(), v);
            }
            return bean;
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException("bean实例化失败");
        }
    }

    private BeanDefinition getBeanDefinition(String beanName) {
        BeanDefinition beanDefinition = definitionMap.get(beanName);
        if (beanDefinition == null) {
            throw new RuntimeException("bean定义尚未定义");
        }
        return beanDefinition;
    }
}
